#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>

#include "cJSON.h"
#include "common.h"

// 日志函数声明
enum LogLevel { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL };
int logInit(const char *filename, enum LogLevel level, int consoleOutput);
void logCleanup();
void logDebug(const char *format, ...);
void logInfo(const char *format, ...);
void logWarning(const char *format, ...);
void logError(const char *format, ...);
void logFatal(const char *format, ...);

// 心跳函数声明
typedef struct HeartbeatConfig HeartbeatConfig;
HeartbeatConfig *heartbeatInit(int interval, int timeout, int (*sendFunc)(void *), void *context);
int heartbeatStart(HeartbeatConfig *config);
void heartbeatStop(HeartbeatConfig *config);
void heartbeatDestroy(HeartbeatConfig *config);

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define HEARTBEAT_INTERVAL 10  // 10秒
#define HEARTBEAT_TIMEOUT 30   // 30秒

// 客户端上下文
typedef struct {
    int sockfd;
    HeartbeatConfig *heartbeat;
    int running;
} ClientContext;

// 发送心跳函数
static int clientSendHeartbeat(void *arg) {
    ClientContext *context = (ClientContext *)arg;
    
    if (context->sockfd <= 0) {
        return -1;
    }
    
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "type", "heartbeat");
    cJSON_AddNumberToObject(root, "timestamp", time(NULL));
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    int ret = sendPacket(context->sockfd, DATA_TYPE_HEARTBEAT, jsonStr);
    
    cJSON_free(jsonStr);
    cJSON_Delete(root);
    
    if (ret < 0) {
        logError("Failed to send heartbeat");
        return -1;
    }
    
    logDebug("Heartbeat sent");
    return 0;
}

// 接收服务器响应
static void *receiveResponse(void *arg) {
    ClientContext *context = (ClientContext *)arg;
    char jsonBuffer[MAX_BUFFER_SIZE];
    unsigned char dataType;
    
    while (context->running) {
        int ret = recvPacket(context->sockfd, jsonBuffer, MAX_BUFFER_SIZE, &dataType);
        if (ret > 0) {
            cJSON *root = cJSON_Parse(jsonBuffer);
            if (root) {
                switch (dataType) {
                    case DATA_TYPE_ACK:
                        logInfo("Received ACK from server");
                        break;
                    case DATA_TYPE_ERROR:
                        {
                            char *message = cJSON_GetObjectItem(root, "message")->valuestring;
                            logError("Received ERROR from server: %s", message);
                        }
                        break;
                    default:
                        logWarning("Received unknown data type: %d", dataType);
                        break;
                }
                cJSON_Delete(root);
            } else {
                logError("Failed to parse response from server");
            }
        } else if (ret == 0 || errno != EAGAIN) {
            logError("Connection to server closed or error occurred");
            context->running = 0;
            break;
        }
        
        usleep(100000);  // 100ms
    }
    
    return NULL;
}

// 发送硅片数据示例
void sendSiliconWaferData(ClientContext *context) {
    cJSON *root = cJSON_CreateObject();
    cJSON *batchArray = cJSON_CreateArray();
    
    // 创建第一条硅片数据
    cJSON *item1 = cJSON_CreateObject();
    cJSON_AddStringToObject(item1, "waferId", "sw00000001");
    cJSON_AddStringToObject(item1, "equipmentId", "EQ003");
    cJSON_AddStringToObject(item1, "ipAddress", "192.168.2.145");
    cJSON_AddStringToObject(item1, "defectType", "隐裂");
    cJSON_AddNumberToObject(item1, "efficiency", 18.65);
    cJSON_AddNumberToObject(item1, "weight", 2.385);
    cJSON_AddStringToObject(item1, "productionTime", "2025-10-15 10:23:48");
    cJSON_AddStringToObject(item1, "productionLineNo", "LINE-05");
    cJSON_AddStringToObject(item1, "reworkFlag", "已返工");
    
    cJSON_AddItemToArray(batchArray, item1);
    cJSON_AddItemToObject(root, "batchSiliconWaferData", batchArray);
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    
    logInfo("Sending silicon wafer data to server");
    int ret = sendPacket(context->sockfd, DATA_TYPE_SILICON_WAFER, jsonStr);
    if (ret < 0) {
        logError("Failed to send silicon wafer data");
    } else {
        logInfo("Silicon wafer data sent successfully");
    }
    
    cJSON_free(jsonStr);
    cJSON_Delete(root);
}

// 发送生产数据示例
void sendProductionData(ClientContext *context) {
    cJSON *root = cJSON_CreateObject();
    cJSON *prodData = cJSON_CreateObject();
    
    cJSON_AddStringToObject(prodData, "shift", "1");
    cJSON_AddStringToObject(prodData, "time", "2025-10-15 08:00-16:00");
    cJSON_AddStringToObject(prodData, "lineNo", "产线05");
    cJSON_AddNumberToObject(prodData, "output", 18500);
    cJSON_AddNumberToObject(prodData, "qualifiedRate", 0.982);
    cJSON_AddNumberToObject(prodData, "aGradeRate", 0.915);
    cJSON_AddNumberToObject(prodData, "reworkRate", 0.013);
    
    cJSON_AddItemToObject(root, "productionData", prodData);
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    
    logInfo("Sending production data to server");
    int ret = sendPacket(context->sockfd, DATA_TYPE_PRODUCTION, jsonStr);
    if (ret < 0) {
        logError("Failed to send production data");
    } else {
        logInfo("Production data sent successfully");
    }
    
    cJSON_free(jsonStr);
    cJSON_Delete(root);
}

// 主函数
int main() {
    ClientContext context;
    pthread_t receiveThread;
    
    // 初始化日志
    logInit("client.log", LOG_LEVEL_INFO, 1);
    logInfo("Starting client...");
    
    // 连接服务器
    context.sockfd = connectTCPServer(SERVER_IP, SERVER_PORT);
    if (context.sockfd < 0) {
        logFatal("Failed to connect to server %s:%d", SERVER_IP, SERVER_PORT);
    }
    
    logInfo("Connected to server %s:%d", SERVER_IP, SERVER_PORT);
    
    // 初始化心跳
    context.heartbeat = heartbeatInit(HEARTBEAT_INTERVAL, HEARTBEAT_TIMEOUT, 
                                     clientSendHeartbeat, &context);
    if (!context.heartbeat) {
        logError("Failed to initialize heartbeat");
    } else {
        heartbeatStart(context.heartbeat);
        logInfo("Heartbeat started with interval %d seconds", HEARTBEAT_INTERVAL);
    }
    
    // 设置运行标志
    context.running = 1;
    
    // 启动接收线程
    pthread_create(&receiveThread, NULL, receiveResponse, &context);
    
    // 发送示例数据
    sendSiliconWaferData(&context);
    sleep(2);
    sendProductionData(&context);
    
    // 运行一段时间后退出
    logInfo("Client running, press Ctrl+C to exit");
    sleep(60);
    
    // 清理资源
    logInfo("Stopping client...");
    context.running = 0;
    
    if (context.heartbeat) {
        heartbeatStop(context.heartbeat);
        heartbeatDestroy(context.heartbeat);
    }
    
    pthread_join(receiveThread, NULL);
    close(context.sockfd);
    logCleanup();
    
    logInfo("Client stopped");
    return 0;
}